﻿using System;
using System.Security.Cryptography;
using System.Text;

namespace Bridge.Workflow.Extensions
{
    /// <summary>
    /// 
    /// </summary>
    public static class SimpleStringCipher
    {
        private static string ToKey()
        {
            return "what21.com";
        }

        /**
         * 加密
         * 
         * @param key
         * @param text
         * @return
         * @throws CipherException
         */
        public static string Encrypt(String key, String text)
        {
            if (text == null)
            {
                return null;
            }
            if (key == null || key.Length <= 0)
            {
                key = ToKey();
            }
            byte[] cipherBytes = null;
            try
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes(key);
                byte[] txtBytes = Encoding.UTF8.GetBytes("{" + text + "}");
                cipherBytes = new byte[txtBytes.Length];
                int i = 0;
                int j = 0;
                for (int k = 0; k < txtBytes.Length; k++)
                {
                    if (k % keyBytes.Length == 0)
                    {
                        i = 0;
                        j++;
                    }
                    cipherBytes[k] = (byte)((txtBytes[k] + ToChar(key, i, j, k)) & 0XFF);
                    cipherBytes[k] = (byte)((cipherBytes[k] - keyBytes[i]) & 0XFF);
                    i++;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            // Base64编码
            return Convert.ToBase64String(cipherBytes);
        }

        /**
         * @param key
         * @param i
         * @param j
         * @param k
         * @return
         */
        private static byte ToChar(string key, int i, int j, int k)
        {
            // MD5随机CODE
            string md5 = MD5Hash(i + "+" + j + "-" + k).ToLower();
            int index = j % md5.Length;
            char[] chars = md5.ToCharArray();
            char c = chars[index];
            return (byte)c;
        }

        public static string MD5Hash(string input)
        {//密文
            string pwd = string.Empty;
            using (var md5 = MD5.Create())
            {
                // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
                byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
                // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
                for (int i = 0; i < s.Length; i++)
                {
                    // 将得到的字符串使用十六进制类型格式。
                    //格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符
                    //X2表示16进制
                    pwd = pwd + s[i].ToString("X2");
                }

                return pwd;
            }
        }

        /**
         * 解密
         * 
         * @param key
         * @param text
         * @return
         * @throws CipherException
         */
        public static String Decrypt(String key, String text)
        {
            if (text == null)
            {
                return null;
            }
            if (key == null || key.Length <= 0)
            {
                key = ToKey();
            }
            try
            {
                // Base64解码
                byte[] cipherBytes = Convert.FromBase64String(key);
                byte[] keyBytes = Encoding.UTF8.GetBytes(key);
                byte[] txtBytes = new byte[cipherBytes.Length];
                int i = 0;
                int j = 0;
                for (int k = 0; k < cipherBytes.Length; k++)
                {
                    if (k % keyBytes.Length == 0)
                    {
                        i = 0;
                        j++;
                    }
                    txtBytes[k] = (byte)((cipherBytes[k] - ToChar(key, i, j, k)) & 0XFF);
                    txtBytes[k] = (byte)((txtBytes[k] + keyBytes[i]) & 0XFF);
                    i++;
                }
                String txt = Encoding.UTF8.GetString(txtBytes);
                return txt.Substring(1, txt.Length - 1);
            }
            catch (Exception e)
            {
                return "";
            }

        }
    }
}
